package com.haodai.agency.net;

import android.text.TextUtils;
import android.util.Base64;

import com.haodai.agency.save.SaveSharedPreferences;
import com.haodai.agency.utils.AESCrypt;
import com.haodai.agency.utils.MD5Util;

import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;

/**
 * addParam(String key, String value) post 请求，且 body type 为 x-www-form-urlencoded 时，键值对公
 * 共参数插入到 body 参数中，其他情况插入到 url query 参数中。
 * addParamsMap(Map paramsMap) 同上，不过这里用键值对 Map 作为参数批量插入。
 * addHeaderParam(String key, String value) 在 header 中插入键值对参数。
 * addHeaderParamsMap(Map headerParamsMap) 在 header 中插入键值对 Map 集合，批量插入。
 * addHeaderLine(String headerLine)在 header 中插入 headerLine 字符串，字符串需要符合
 * -1 != headerLine.indexOf(“:”) 的规则，即可以解析成键值对。
 * addHeaderLinesList(List headerLinesList)同上，headerLineList: List 为参数，批量插入 headerLine。
 * addQueryParam(String key, String value)插入键值对参数到 url query 中。
 * addQueryParamsMap(Map queryParamsMap)插入键值对参数 map 到 url query 中，批量插入。
 */

public class BasicParamsInterceptor implements Interceptor {

    private static final String TAG = BasicParamsInterceptor.class.getSimpleName();

    Map<String, String> queryParamsMap = new HashMap<>();
    Map<String, String> paramsMap = new HashMap<>();
    Map<String, String> headerParamsMap = new HashMap<>();
    List<String> headerLinesList = new ArrayList<>();

    private BasicParamsInterceptor() {

    }

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request request = chain.request();
        Request.Builder requestBuilder = request.newBuilder();

        // process header params inject
        if (headerParamsMap != null && headerParamsMap.size() > 0) {
            Set<String> keys = headerParamsMap.keySet();
            for (String headerKey : keys) {
                requestBuilder.addHeader(headerKey, headerParamsMap.get(headerKey)).build();
            }
        }

        Headers.Builder headerBuilder = request.headers().newBuilder();
        if (headerLinesList.size() > 0) {
            for (String line : headerLinesList) {
                headerBuilder.add(line);
            }
            requestBuilder.headers(headerBuilder.build());
        }
        // process header params end


        // process queryParams inject whatever it's GET or POST
        if (queryParamsMap.size() > 0) {
            request = injectParamsIntoUrl(request.url().newBuilder(), requestBuilder, queryParamsMap);
        }

        paramsMap.put("token", SaveSharedPreferences.getToken());
        paramsMap.put("timestamp", System.currentTimeMillis()/1000+"");
        // process post body inject
        if (paramsMap.size() > 0) {
            if (canInjectIntoBody(request)) {
                FormBody.Builder formBodyBuilder = new FormBody.Builder();

                for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
                    formBodyBuilder.add((String) entry.getKey(), (String) entry.getValue());
                }
                String postBodyString=bodyToString(request.body());
                //请求的data数据
                String sign_data="";
                String start=postBodyString;
                String end="";
                if(postBodyString.contains("data=")) {
                    String[] strs = postBodyString.split("data=");
                    sign_data = strs[1];
                    start=strs[0];
                }

                if(sign_data.contains("&")){
                    String[] strs = sign_data.split("&");
                    end=sign_data.replace(strs[0],"");
                    sign_data=strs[0];
                }

                postBodyString=start+end;
                if(sign_data!=""){
                    sign_data=URLDecoder.decode(sign_data);
                    //获取公参中的数据
                    String timestamp= paramsMap.get("timestamp");
                    String token= paramsMap.get("token");
                    String key= AESCrypt.SIGN_KEY;
                    String sign="";
                    //构建请求签名sign
                    if(timestamp!=null&&token!=null){
                        String base64Data =  new String(Base64.encode((sign_data + token + timestamp).trim().getBytes(),
                                Base64.DEFAULT), "UTF-8");
                        sign=AESCrypt.SIGN_KEY + base64Data.trim().replace("\n","") + AESCrypt.SIGN_KEY;

                        formBodyBuilder.add("sign", MD5Util.myMd5(sign.trim()).toLowerCase());
                    }
                    formBodyBuilder.add("data",AESCrypt.getInstance().encrypt(sign_data));
                }
                RequestBody formBody = formBodyBuilder.build();
                postBodyString += ((postBodyString.length() > 0) ? "&" : "") + bodyToString(formBody);
                requestBuilder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString));
            }
        }

        request = requestBuilder.build();
        return chain.proceed(request);
    }

    private boolean canInjectIntoBody(Request request) {
        if (request == null) {
            return false;
        }
        if (!TextUtils.equals(request.method(), "POST")) {
            return false;
        }
        RequestBody body = request.body();
        if (body == null) {
            return false;
        }
        MediaType mediaType = body.contentType();
        if (mediaType == null) {
            return false;
        }
        if (!TextUtils.equals(mediaType.subtype(), "x-www-form-urlencoded")) {
            return false;
        }
        return true;
    }

    // func to inject params into url
    private Request injectParamsIntoUrl(HttpUrl.Builder httpUrlBuilder, Request.Builder requestBuilder, Map<String, String> paramsMap) {
        if (paramsMap.size() > 0) {
            Iterator iterator = paramsMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                httpUrlBuilder.addQueryParameter((String) entry.getKey(), (String) entry.getValue());
            }
            requestBuilder.url(httpUrlBuilder.build());
            return requestBuilder.build();
        }

        return null;
    }

    private static String bodyToString(final RequestBody request) {
        try {
            final RequestBody copy = request;
            final Buffer buffer = new Buffer();
            if (copy != null)
                copy.writeTo(buffer);
            else
                return "";
            return buffer.readUtf8();
        } catch (final IOException e) {
            return "did not work";
        }
    }

    public static class Builder {

        BasicParamsInterceptor interceptor;

        public Builder() {
            interceptor = new BasicParamsInterceptor();
        }

        public Builder addParam(String key, String value) {
            interceptor.paramsMap.put(key, value);
            return this;
        }

        public Builder addParamsMap(Map<String, String> paramsMap) {
            interceptor.paramsMap.putAll(paramsMap);
            return this;
        }

        public Builder addHeaderParam(String key, String value) {
            interceptor.headerParamsMap.put(key, value);
            return this;
        }

        public Builder addHeaderParamsMap(Map<String, String> headerParamsMap) {
            interceptor.headerParamsMap.putAll(headerParamsMap);
            return this;
        }

        public Builder addHeaderLine(String headerLine) {
            int index = headerLine.indexOf(":");
            if (index == -1) {
                throw new IllegalArgumentException("Unexpected header: " + headerLine);
            }
            interceptor.headerLinesList.add(headerLine);
            return this;
        }

        public Builder addHeaderLinesList(List<String> headerLinesList) {
            for (String headerLine : headerLinesList) {
                int index = headerLine.indexOf(":");
                if (index == -1) {
                    throw new IllegalArgumentException("Unexpected header: " + headerLine);
                }
                interceptor.headerLinesList.add(headerLine);
            }
            return this;
        }

        public Builder addQueryParam(String key, String value) {
            interceptor.queryParamsMap.put(key, value);
            return this;
        }

        public Builder addQueryParamsMap(Map<String, String> queryParamsMap) {
            interceptor.queryParamsMap.putAll(queryParamsMap);
            return this;
        }

        public BasicParamsInterceptor build() {
            return interceptor;
        }

    }
}
